/*
  libsmtp is a library to send mail via SMTP

Copyright � 2001 Kevin Read <obsidian@berlios.de>

This software is available under the GNU Lesser Public License as described
in the COPYING file.

This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or any later version.

This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

Kevin Read <obsidian@berlios.de>
Thu Aug 16 2001 */

#include <glib.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <netdb.h>
#include <stdio.h>
#include <unistd.h>
#include <netinet/in.h>
#include <string.h>
#include <time.h>

#include "../config.h"
#include "libsmtp.h"
int    _write_file_email=-1;
char   _log_mail_buffer[512]={ 0 };
#ifdef LIBSMTP_DEBUG

int    _log_file_email=-1;

#endif
int libsmtp_connect (char *libsmtp_server, unsigned int libsmtp_port, unsigned int libsmtp_flags, struct libsmtp_session_struct *libsmtp_session)
{
  int libsmtp_socket,_kk; 		/* The temporary socket handle */
  int libsmtp_bytes_read=0;     /* How many bytes read? */
  struct hostent *libsmtp_mailhost;	/* We need this to convert the hostname to an IP */
  struct sockaddr_in libsmtp_sock;	/* We need this for the connection */
  gchar *libsmtp_temp_buffer[4096];	/* Temp string for reads and writes */
//  char *libsmtp_search_buffer;		/* Used for searching in strings */
  GString *libsmtp_temp_gstring;	/* Temp gstring */
  char mail_file[200]={ 0 };
  char mail_data[200]={ 0 };
  char mail_subject[200]= { 0 };
  char mail_namefile[200]={ 0 };
  struct tm *p;
  long clock;

  clock = (long)time((long *)0);
  p = localtime(&clock);
  /* We clear up the variable space and instantiate the GStrings */
  #ifdef LIBSMTP_DEBUG
  _log_file_email = open("/tmp/lib_smtp.txt", O_WRONLY | O_CREAT | O_TRUNC , S_IRWXU | S_IRWXG | S_IRWXO);
  #endif
  strftime(mail_data,200,"%d.%m.%Y",p);
  sprintf(mail_subject,"%s",libsmtp_session->Subject->str);
  for(_kk=0;_kk<strlen(mail_subject);_kk++){
      if(iscntrl(mail_subject[_kk]) || ispunct(mail_subject[_kk]) || mail_subject[_kk]==' ')mail_subject[_kk]='_';
  }
  sprintf(mail_namefile,"%s_%s",mail_subject,mail_data);
  sprintf(mail_namefile+strlen(mail_namefile),"_%02d.%02d.%02d.eml",p->tm_hour,p->tm_min,p->tm_sec);


  sprintf(mail_file,"/tmp/mail/%s",mail_namefile);
  _write_file_email = open(mail_file, O_WRONLY | O_CREAT | O_TRUNC , S_IRWXU | S_IRWXG | S_IRWXO);
  bzero (libsmtp_temp_buffer, sizeof(libsmtp_temp_buffer));



  libsmtp_temp_gstring = g_string_new (NULL);

  /* We enter the connect stage now */
  libsmtp_session->Stage = LIBSMTP_CONNECT_STAGE;

  /* We need a socket anyway :) */
  libsmtp_socket = socket (PF_INET, SOCK_STREAM, 0);

  /* Socket ok? */
  if (libsmtp_socket < 0)
  {
    libsmtp_session->ErrorCode = LIBSMTP_SOCKETNOCREATE;
    g_string_free (libsmtp_temp_gstring,1);
    return LIBSMTP_SOCKETNOCREATE;
  }


  g_string_sprintf (libsmtp_session->Path, "/tmp/mail/");
  g_string_sprintf (libsmtp_session->Filename, "%s", mail_namefile);
  /* Now we need to get the IP from the hostname... */
  if ((libsmtp_mailhost=gethostbyname((const char *)libsmtp_server))==NULL)
  {
/*    printf ("Host %s not found with error ", libsmtp_server);
    perror ("host"); */
    libsmtp_session->ErrorCode = LIBSMTP_HOSTNOTFOUND;
    g_string_free (libsmtp_temp_gstring,1);
    close (libsmtp_socket);
    libsmtp_session->socket=0;
  #ifdef LIBSMTP_DEBUG
  if(_log_file_email>-1){
	close(_log_file_email);
	_log_file_email=-1;
  }
  #endif
  if(_write_file_email>-1){
	close(_write_file_email);
	_write_file_email=-1;
  }
    return LIBSMTP_HOSTNOTFOUND;
  }

  /* This struct is needed for the connect call */
  libsmtp_sock.sin_family = AF_INET;
  libsmtp_sock.sin_addr = *(struct in_addr *)libsmtp_mailhost->h_addr;
  if (!libsmtp_port)
    libsmtp_sock.sin_port = htons (25);
  else
    libsmtp_sock.sin_port = htons (libsmtp_port);

  /* Now we make the connection to the smart host on the specified port */

  if (connect (libsmtp_socket, (struct sockaddr *) &libsmtp_sock, sizeof (libsmtp_sock) ) < 0)
  {
    libsmtp_session->ErrorCode = LIBSMTP_CONNECTERR;
    g_string_free (libsmtp_temp_gstring,1);
    close (libsmtp_socket);
    libsmtp_session->socket=0;
  #ifdef LIBSMTP_DEBUG
  if(_log_file_email>-1){
	close(_log_file_email);
	_log_file_email=-1;
  }
  #endif
  if(_write_file_email>-1){
	close(_write_file_email);
	_write_file_email=-1;
  }
    return LIBSMTP_CONNECTERR;
  }


  /* Ok, lets set the session socket to the right handler */
  libsmtp_session->socket = libsmtp_socket;

  /* We enter the greet stage now */
  libsmtp_session->Stage = LIBSMTP_GREET_STAGE;

  /* Now we should read the mail servers greeting */
  if (libsmtp_int_read (libsmtp_temp_gstring, libsmtp_session, 2))
    return LIBSMTP_ERRORREADFATAL;

  if (libsmtp_session->LastResponseCode != 220)
  {
    libsmtp_session->ErrorCode = LIBSMTP_NOTWELCOME;
    g_string_free (libsmtp_temp_gstring,1);
    close (libsmtp_session->socket);
    libsmtp_session->socket=0;
  #ifdef LIBSMTP_DEBUG
  if(_log_file_email>-1){
	close(_log_file_email);
	_log_file_email=-1;
  }
  #endif
  if(_write_file_email>-1){
	close(_write_file_email);
	_write_file_email=-1;
  }
    return LIBSMTP_NOTWELCOME;
  }

  /* Now we need to know our hostname */

  if (gethostname ((char *)libsmtp_temp_buffer, sizeof(libsmtp_temp_buffer)))
  {
    libsmtp_session->ErrorCode = LIBSMTP_WHATSMYHOSTNAME;
    g_string_free (libsmtp_temp_gstring,1);
    close (libsmtp_session->socket);
    libsmtp_session->socket=0;
  #ifdef LIBSMTP_DEBUG
  if(_log_file_email>-1){
	close(_log_file_email);
	_log_file_email=-1;
  }
  #endif
  if(_write_file_email>-1){
	close(_write_file_email);
	_write_file_email=-1;
  }
    return LIBSMTP_WHATSMYHOSTNAME;
  }

  /* We enter the hello stage now */
  libsmtp_session->Stage = LIBSMTP_HELLO_STAGE;

  /* Ok, lets greet him back */

  g_string_sprintf (libsmtp_temp_gstring, "EHLO %s\r\n", libsmtp_temp_buffer);

  if (libsmtp_int_send (libsmtp_temp_gstring, libsmtp_session, 2,0)){
      g_string_free (libsmtp_temp_gstring,1);
      return LIBSMTP_ERRORSENDFATAL;
  }

  /* After this he will send us his capabilities. He may not be able to
     recognize EHLO though, so we have to send HELO instead. */

  if (libsmtp_int_read (libsmtp_temp_gstring, libsmtp_session, 2)){
      g_string_free (libsmtp_temp_gstring,1);
      return LIBSMTP_ERRORSENDFATAL;
  }

  if (libsmtp_session->LastResponseCode < 300)
  {
    /* Ok, he loves us. Lets parse the response for the capabilities. */

    if (strstr (libsmtp_session->LastResponse->str, "8BITMIME"))
      libsmtp_session->serverflags |= LIBSMTP_HAS_8BIT;

    if (strstr (libsmtp_session->LastResponse->str, "PIPELINING"))
      libsmtp_session->serverflags |= LIBSMTP_HAS_PIPELINING;

    if (strstr (libsmtp_session->LastResponse->str, "DSN"))
      libsmtp_session->serverflags |= LIBSMTP_HAS_DSN;

    if (strstr (libsmtp_session->LastResponse->str, "STARTTLS"))
      libsmtp_session->serverflags |= LIBSMTP_HAS_TLS;

    if (strstr (libsmtp_session->LastResponse->str, "AUTH"))
      libsmtp_session->serverflags |= LIBSMTP_HAS_AUTH;

    if (strstr (libsmtp_session->LastResponse->str, "SIZE"))
      libsmtp_session->serverflags |= LIBSMTP_HAS_SIZE;

    if (strstr (libsmtp_session->LastResponse->str, "ETRN"))
      libsmtp_session->serverflags |= LIBSMTP_HAS_ETRN;

    if (strstr (libsmtp_session->LastResponse->str, "ENHANCEDSTATUSCODES"))
      libsmtp_session->serverflags |= LIBSMTP_HAS_ENHANCEDSTATUSCODES;

    /* Ok, now we're ready for business */

  }
  else
  {
    /* Ok, he doesn't understand EHLO, so we will send HELO instead */
    g_string_sprintf (libsmtp_temp_gstring, "HELO %s\r\n", libsmtp_temp_buffer);

    if (libsmtp_int_send (libsmtp_temp_gstring, libsmtp_session, 2,0)){
        g_string_free (libsmtp_temp_gstring,1);
        return LIBSMTP_ERRORSENDFATAL;
    }

    /* Lets see if he likes us now. */

    if (libsmtp_session->LastResponseCode > 299)
    {
      /* We are not welcome here it seems - I don't know if this is fatal
         to SMTP transactions - FIXME */
      libsmtp_session->ErrorCode=LIBSMTP_NOTWELCOME;
      g_string_free (libsmtp_temp_gstring,1);
      close (libsmtp_session->socket);
      libsmtp_session->socket=0;
  #ifdef LIBSMTP_DEBUG
  if(_log_file_email>-1){
	close(_log_file_email);
	_log_file_email=-1;
  }
  #endif
  if(_write_file_email>-1){
	close(_write_file_email);
	_write_file_email=-1;
  }
      return LIBSMTP_NOTWELCOME;

    }

    /* All capabilities are at 0 - This server is really stupid i. e. Exchange */
  }

  /* Ok, we're ready now. The connection is set up. */
  g_string_free (libsmtp_temp_gstring,1);
  return LIBSMTP_NOERR;
}

char * libgetFileSave(struct libsmtp_session_struct *libsmtp_session,char * path,char * name){

    sprintf(path,"%s",libsmtp_session->Path->str);
    sprintf(name,"%s",libsmtp_session->Filename->str);
    return name;
}

int libsmtp_close (struct libsmtp_session_struct *libsmtp_session)
{
  /* I just hope that there are no socket with fd 0 out there :) */
  if (libsmtp_session->socket)
  {
    close (libsmtp_session->socket);
    libsmtp_session->socket=0;
  }
  #ifdef LIBSMTP_DEBUG
  if(_log_file_email>-1){
	close(_log_file_email);
	_log_file_email=-1;
  }
  #endif
  if(_write_file_email>-1){
	close(_write_file_email);
	_write_file_email=-1;
  }

  return LIBSMTP_NOERR;
}
